package org.example.springboot.controller;



import ch.qos.logback.classic.Logger;
import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import com.alibaba.fastjson.JSONObject;
import jakarta.annotation.Resource;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.apache.catalina.filters.ExpiresFilter;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.util.EntityUtils;
import org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream;
import org.example.springboot.common.Result;
import org.example.springboot.config.WechatConfig;
import org.example.springboot.entity.WxMember;
import org.example.springboot.service.WxMemberService;
import org.example.springboot.utils.WechatHttpUtils;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@CrossOrigin(origins = {"http://localhost:5173"}, allowCredentials = "true")
@RestController
@RequestMapping(value="/wechat", produces = "application/json;charset=UTF-8")
public class WxApiController {
    @Resource
    private WechatConfig wechatConfig;
    @Resource
    private WxMemberService wxMemberService;
    WxMember wxMember;
    // 全局存储二维码登录状态
    private static final Map<String, WxMember> LOGIN_CACHE = new HashMap<>();
    // 定义未登录标记
    private static final WxMember UNLOGGED = new WxMember();


    //用于微信接口配置信息的
    @GetMapping("/wxCheck")
    public String wxCheck(
            @RequestParam("signature") String signature,
            @RequestParam("timestamp") String timestamp,
            @RequestParam("nonce") String nonce,
            @RequestParam("echostr") String echostr
    ) {
        try {
            // 1. 获取 Token（确保与微信测试号后台一致）
            String token = "abcd123";

            // 2. 将 token、timestamp、nonce 按字典序排序
            String[] arr = {token, timestamp, nonce};
            Arrays.sort(arr);

            // 3. 拼接排序后的字符串
            StringBuilder content = new StringBuilder();
            for (String s : arr) {
                content.append(s);
            }

            // 4. SHA-1 加密
            String ciphertext = DigestUtils.sha1Hex(content.toString());

            // 5. 校验签名
            if (ciphertext.equals(signature)) {
                // 校验通过，返回 echostr
                return echostr;
            } else {
                // 校验失败
                return "Invalid Signature";
            }
        } catch (Exception e) {
            // 打印异常信息
            e.printStackTrace();
            return "System Error";
        }
    }

    //查询用户
    @GetMapping("/selectWxMember")
    public Result select(){
        List<WxMember> list = wxMemberService.select();
        return Result.success(list);
    }

    //第一步请求CODE
    //生成微信二维码
    @CrossOrigin(origins = {"http://localhost:5173"})//允许前端跨域访问
    @GetMapping("/login")
    public Result getWxCode(HttpServletResponse response) throws IOException {
        // 生成唯一令牌（替代Session的身份标识）
        String token = UUID.randomUUID().toString().replace("-", "");
        //1、访问这个地址，微信开发平台会让用户确定是否登录
        String baseUrl = "https://open.weixin.qq.com/connect/oauth2/authorize"+
                "?appid=%s"+
                "&redirect_uri=%s"+
                "&response_type=code"+
                "&scope=snsapi_userinfo"+
                "&state=%s"+ // 用token作为state，关联回调
                "#wechat_redirect";

        //2、对redirectUri进行URLEncoder编码
        String redirectUri = wechatConfig.getRedirectUri();
        try {
            redirectUri = URLEncoder.encode(redirectUri,"utf-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        //3、给占位符赋值
        String url = String.format(baseUrl, wechatConfig.getAppId(), redirectUri, token);
        //2. 生成二维码并写入响应流（直接返回给前端，不保存本地文件）
//        response.setContentType("image/png"); // 设置响应类型为图片
//        QrCodeUtil.generate(url, 300, 300,"png",response.getOutputStream());
        //4、重定向到请求微信地址里面
        // 2. 生成二维码并转为Base64
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        QrCodeUtil.generate(url, 300, 300, "png", outputStream);
        byte[] imageBytes = outputStream.toByteArray();
        String base64QrCode = "data:image/png;base64," + Base64.getEncoder().encodeToString(imageBytes);

        // 令牌暂时存入缓存（状态为“未登录”）
        LOGIN_CACHE.put(token, UNLOGGED);

        return Result.success(url).put("qrcode",base64QrCode).put("token", token);
        //如果用户同意授权，页面将跳转至授权链接的 redirectUri 参数所示链接中，并附带 code 和 state
    }

    //第二步：拿到code后通过code获取access_token
    @CrossOrigin(origins = {"http://localhost:5173"})//允许前端跨域访问
    @GetMapping("callback")
    public Result callback(String code, String state) throws UnsupportedEncodingException {
        // state即前端的token（从login接口传递而来）
        String token = state;
        //1、拿着code请求微信固定的地址，得到两个值access_token 和 openid
        System.out.println("拿到的code是" + code);
        String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token"+
                "?appid=%s" +
                "&secret=%s"+
                "&code=%s"+
                "&grant_type=authorization_code";
        //2、给占位符赋值
        String accessTokenUrl = String.format(baseAccessTokenUrl,wechatConfig.getAppId(),wechatConfig.getAppSecret(),code);
        //3、向认证服务器发送请求换取access_token
        //请求这个拼接好的地址，得到返回的access_token和openid
        //使用httpclient发送请求，得到返回结果
        // (httpclient就是能够在不是用浏览器的情况下也能模拟出浏览器的请求和响应过程）

        CloseableHttpResponse response = null;
        HttpGet httpGet = new HttpGet(accessTokenUrl);
//        WxMember wxMember = null;
        String openid;
        Map<String, Object> params = new HashMap<String, Object>();
        try {
            response = WechatHttpUtils.getClient().execute(httpGet);
            //得到一个状态码
            int statusCode = response.getStatusLine().getStatusCode();
            //把它转化为一个JSON对象
//            JSONObject jsonObject = JSONObject.parseObject(EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8));
            String responseStr = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            System.out.println("微信接口返回原始数据：" + responseStr);  // 打印原始响应，排查接口错误
            JSONObject jsonObject = JSONObject.parseObject(responseStr);
            //转化为JSON对象后，可以获取到以下内容 获取到以下内容就可以获取到微信用户的信息了
            /*
            正确时返回内容：
            {
              "access_token":"ACCESS_TOKEN",
              "expires_in":7200,
              "refresh_token":"REFRESH_TOKEN",
              "openid":"OPENID",
              "scope":"SCOPE",
              "is_snapshotuser": 1,
              "unionid": "UNIONID"
            }
             */
            // 2. 优先判断微信返回的错误码
            if (jsonObject.containsKey("errcode")) {
                int errCode = jsonObject.getIntValue("errcode");
                String errMsg = jsonObject.getString("errmsg");
                // 直接返回错误，不执行后续逻辑
                return Result.error("500" , "微信授权失败：" + errCode + "，" + errMsg);
            }

            // 3. 只有无错误时才提取参数
            String accessToken = jsonObject.getString("access_token");
            openid = jsonObject.getString("openid");
            String unionid = jsonObject.getString("unionid");
            System.out.println(unionid);
            //调用微信用户信息
            wxMember = this.getWxMemberInfo(accessToken,openid);
            // 补充：校验openid是否为空（防御性判断）
            if (openid == null || openid.isEmpty()) {
                return Result.error("500", "获取openid失败");
            }
        } catch (Exception e) {
            if (e instanceof IOException) {

                return Result.error("500","网络连接异常，请稍后重试");
            } else if (e instanceof Exception) {
                return Result.error("500","微信返回数据解析错误，请检查配置");
            } else {
                e.printStackTrace();
                return Result.error("500","系统错误");
            }
        }
        // 检查数据库中是否存在该用户
        List<WxMember> existingUser = wxMemberService.selectByOpenid(openid);
        if (existingUser.isEmpty()) {
            // 不存在则保存用户信息
            wxMemberService.saveOrUpdate(wxMember);
        }else {
            wxMember = existingUser.get(0); // 如果用户已存在，使用现有用户信息
        }

        // 将用户信息存入缓存（关联token）
        LOGIN_CACHE.put(token, wxMember);

        return  Result.success(wxMember);
    }
    @CrossOrigin(origins = {"http://localhost:5173"})//允许前端跨域访问
    @GetMapping("/checkLogin")
    public Result checkLogin(@RequestParam String token) {
        WxMember user = LOGIN_CACHE.get(token);
        if (user != null && user != UNLOGGED) {
            // 登录成功，从缓存移除令牌（避免重复使用）
            LOGIN_CACHE.remove(token);
            return Result.success(user);
        } else {
            return Result.error("401", "未登录");
        }
    }

    //获取微信用户信息方法
    public WxMember getWxMemberInfo(String accessToken,String openid){
        //定义一个请求连接
        URIBuilder uriBuilder = null;
        //定义一个微信用户
        WxMember wxMember = null;
        //get请求的对象
        HttpGet httpGet = null;
        //发出get请求后得到一个返回对象
        CloseableHttpResponse response = null;
        try {
            //调用拉取用户信息的api 需要传递三个参数
            uriBuilder = new URIBuilder("https://api.weixin.qq.com/sns/userinfo?");
            uriBuilder.setParameter("access_token", accessToken);
            uriBuilder.setParameter("openid", openid);
            uriBuilder.setParameter("lang", "zh_CN");
            //发出get请求
            httpGet = new HttpGet(uriBuilder.build());
            //得到一个返回对象
            response = WechatHttpUtils.getClient().execute(httpGet);
            //封装成一个json对象
            JSONObject jsonObject = JSONObject.parseObject(EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8));
            /*
            正确时返回内容：
            {
              "openid": "OPENID",
              "nickname": NICKNAME,
              "sex": 1,
              "province":"PROVINCE",
              "city":"CITY",
              "country":"COUNTRY",
              "headimgurl":"https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
              "privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ],
              "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
            }
             */

            //将获取到的内容封装成一个对象
            wxMember = new WxMember();
            wxMember.setUnionid(jsonObject.getString("unionid"));
            wxMember.setOpenid(jsonObject.getString("openid"));
            wxMember.setNickname(jsonObject.getString("nickname"));
            wxMember.setHeadimgurl(jsonObject.getString("headimgurl"));
            //调用service层保存到数据库中
//            wxMemberService.saveOrUpdate(wxMember);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return  wxMember;
    }

}
